import pymysql
from pymysql import OperationalError, ProgrammingError, InternalError
import traceback
import re
'''
为了解决 一个表中 多个主键的唯一性
需要使用unique()方法 来设置 多个 键的唯一性
注意 使用 unique(key)方法设置的key 不是 该表的主键
MySQL中没有多个主键，只要主键、外键、组合键、索引
不能同时存在多个独立的PRIMARY KEY，但可以有多个 unique
使用unique()语句来确保指定key的唯一性，同时也保证了 主键的唯一性
'''

config = {
    'host': '127.0.0.1',
    'port': 3307,
    'user': 'root',
    'passwd': '123456',
    'db': 'py02db',
    'charset': 'utf8'
}


def connect_db():
    try:
        connect = pymysql.connect(**config)
        return connect
    except OperationalError as e:
        # OperationalError 用于捕捉PyMySQL的错误机制，目的是不会出现异常
        print(e)
    except InternalError as e:
        print(e)


def query_insert_one(table_name, data):

    insert_data = [
        ('u_uid','12345678907'),
        ('u_name','Tony 托尼'),
        ('u_age', 40)
    ]

    head = []
    values = []
    temps = []
    for item in insert_data:
        head.append(item[0])
        values.append(item[1])
        temps.append('%s')

    '''将 List 转换成 tuple 元组数据集合'''
    head = tuple(head)
    values = tuple(values)
    temps = tuple(temps)

    '''拼接 数据库执行语句 字符串'''
    base_url = "insert into "
    base_url += table_name + str(head) + ' values' + str(temps)
    '''利用正则 去掉  ' 单引号'''
    base_url = re.sub(r'\'', '', base_url)
    connect = connect_db()
    if connect:
        cursor = connect.cursor(cursor=pymysql.cursors.DictCursor)
        try:
            '''使用 execute() 方法执行SQL语句 防注入'''
            cursor.execute(base_url, values)
            '''提交修改数据 并保存'''
            connect.commit()
        except:
            traceback.print_exc()
            connect.rollback()
        finally:
            cursor.close()
            connect.close()


def query_find_all(table_name):
    if table_name is None:
        return
    # 使用正则 过滤 非法字符

    sql_string = "select * from " + table_name
    connect = connect_db()
    if connect:
        cursor = connect.cursor(cursor=pymysql.cursors.DictCursor)
        try:
            cursor.execute(sql_string)
            return cursor.fetchall()
        except ProgrammingError as e:
            print(e)
            # traceback.print_exc()
            connect.rollback()
        finally:
            cursor.close()
            connect.close()
    else:
        return None


def query_search_rows(table_name, condition):

    # 对table_name 进行 正则

    # 构造字符串 构造语句
    # sql_string = "select u_uid,u_name from stu where u_uid='%s' and u_name='%s'" % ("'or 1=1 --", 'Pony pass')

    '''
    SQL注入是比较常见的网络攻击方式之一，它不是利用操作系统的Bug来实现攻击的
    而是针对程序猿在编程时的疏忽，通过SQL语句，实现无账号登录，甚至是修改数据库
    注入总体思路：
    1.寻找到SQL注入的位置
    2.判断服务器类型和后台数据类型
    3.针对不同的服务器和数据库进行SQL注入攻击

    SQL注入攻击的方式1：
    方式1：
    通过字符串拼接查询，造成注入
    u_uid=''or 1=1 --' and u_name='Pony pass'
    相当于 u_uid=''或者'1=1' 那么这个条件就一定成立
    -- 表示注释 它将后面的语句进行注释，不起作用，这样语句就能永远正常执行
    '''

    '''解决方式：参数化语句'''
    # sql_string = "select u_uid,u_name from stu where u_uid='%s'
    # and u_name='%s'",("'or 1=1 --", 'Pony pass')
    # connect_db().cursor().execute("select u_uid,u_name from stu where u_uid='%s' and u_name='%s'", ("'or 1=1 --", 'Pony pass'))








# def a_func(arg2,arg1,arg3,arg4=None):
#     print('arg1:',arg1)
#     print('arg2:', arg2)
#     print('arg3:', arg3)
#     print('arg4:', arg4)



def main():
    # rows = query_find_all('stu')
    # if rows:
    #     print(rows)
    # dict = {
    #     'arg1':1,
    #     'arg2':2,
    #     'arg3':3
    # }
    # a_func(**dict)
    # query_search_rows('stu', '')
    query_insert_one('stu', '')


if __name__ == '__main__':
    main()













